#pragma once
#include "Common.hpp"
#include "InterAddr.hpp"
const int gbacklog = 8;
class Socket
{
public:
    virtual ~Socket() {}
    virtual void CreateSocketOrDie() = 0;                // 创建
    virtual void BindSocketOrDie(uint16_t prot) = 0;     // 绑定
    virtual int ListenSocketOrDie(int backlog) = 0;      // 监听
    virtual int AccpetSocketOrDie(InetAddr *client) = 0; // 获取
    virtual int Recv(std::string *out) = 0;              //接受
    virtual int Send(const std::string &message) = 0;    //发送

    virtual void ConnectSocketOrDie() = 0; // 客户端申请
    virtual int Connect(const std::string &server_ip, uint16_t port) = 0;
    virtual void Close() = 0;
    void BuildTcpSocketMethod(uint16_t port, int backlog = gbacklog)
    {
        CreateSocketOrDie();
        BindSocketOrDie(port);
        ListenSocketOrDie(backlog);
    }
     void BuildTcpClientSocketMethod()
     {
 CreateSocketOrDie();
     }
};

class TcpSocket : public Socket
{
    TcpSocket() {}
    void CreateSocketOrDie() override
    {
        _sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_sockfd < 0)
        {
            perror("socket fail");
            exit(SOCKET_FAIL);
        }
        else
            printf("socket success:%d\n", _sockfd);
    }
    void BindSocketOrDie(uint16_t port) override // 我需要端口号
    {
        // 进行绑定
        InetAddr localaddr(port);
        int n = bind(_sockfd, localaddr.NetAddrPtr(), localaddr.NetAddrLen());
        if (n < 0)
        {
            perror("bind fail\n");
            exit(BIND_FAIL);
        }
        else
        {
            printf("bind success\n");
        }
    }
    // 将套接字设置为监听装状态
    int ListenSocketOrDie(int backlog) override
    {
        int n = listen(_sockfd, backlog);
        if (n < 0)
        {
            perror("listen fail\n");
            exit(LISTEN_FAIL);
        }
        else
            printf("listen success\n");
    }
    int AccpetSocketOrDie(InetAddr *client) override
    {
        InetAddr peer;
        socklen_t len = peer.NetAddrLen();
        int n = accept(_sockfd, CONV(peer), &len);
        if (n < 0)
        {
            perror("accpet fail\n");
        }
        else
        {
            printf("accept success\n");
        }
        return n;
    }

    int Recv(std::string *out) override
    {
        char buffer[1024];
        int n=recv(_sockfd,buffer,sizeof(buffer)-1,0);
        if(n>0)
        {
            buffer[n]=0;
            *out+=buffer;
        }
        return n;
    }
    int Send(const std::string &message) override
    {
      
       return send(_sockfd,message.c_str(),message.size(),0);

    }
    int Connect(const std::string &server_ip, uint16_t port) override
        {
            InetAddr server(server_ip, port);
            return ::connect(_sockfd, server.NetAddrPtr(), server.NetAddrLen());
        }
    void Close() override
    {
        close(_sockfd);
    }
    ~TcpSocket() {}

private:
    int _sockfd;
   
};